home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!zephyr.ens.tek.com!tekred!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v11i088: larn - dungeon type adventure game, Part05/11
- Message-ID: <6719@tekred.CNA.TEK.COM>
- Date: 18 Dec 90 18:33:41 GMT
- Sender: news@tekred.CNA.TEK.COM
- Lines: 1682
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: routley@tle.ENET.DEC.COM (Kevin Routley)
- Posting-number: Volume 11, Issue 88
- Archive-name: larn/Part05
- Environment: Unix, VMS, MS-DOS, termcap
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 11)."
- # Contents: Makefile movem.c savelev.c spells.c
- # Wrapped by billr@saab on Tue Dec 18 10:14:18 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(402 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- XOBJ= action.o bill.o config.o create.o data.o diag.o display.o \
- X fortune.o global.o help.o io.o main.o monster.o \
- X moreobj.o movem.o msdos.o nap.o object.o regen.o savelev.o \
- X scores.o signal.o spells.o spheres.o store.o \
- X tok.o vms.o
- X#
- X#
- X
- XCFLAGS=-DDGK -DBSD -D'LARNHOME="/usr/users/routley/larncc/"'
- X
- Xlarn122: $(OBJ)
- X cc -o larn122 $(OBJ) -ltermcap
- X
- X.c.o:
- X cc $(CFLAGS) -c $*.c
- X
- X.c: header.h
- X
- END_OF_FILE
- if test 402 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'movem.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'movem.c'\"
- else
- echo shar: Extracting \"'movem.c'\" \(18818 characters\)
- sed "s/^X//" >'movem.c' <<'END_OF_FILE'
- X/*
- X * movem.c (move monster) Larn is copyrighted 1986 by Noah Morgan.
- X *
- X * Here are the functions in this file:
- X *
- X * movemonst() Routine to move the monsters toward the player
- X * build_proximity_ripple() Build proximity ripple for smart monster move
- X * move_scared() Move scared monsters
- X * move_smart() Move smart monsters
- X * move_dumb() Move dumb monsters
- X * mmove(x,y,xd,yd) Function to actually perform the monster movement
- X */
- X#include "header.h"
- X#define min(x,y) (((x)>(y))?(y):(x))
- X#define max(x,y) (((x)>(y))?(x):(y))
- X
- Xvoid movemonst();
- Xvoid build_proximity_ripple();
- Xvoid move_scared();
- Xvoid move_smart();
- Xvoid move_dumb();
- Xvoid mmove();
- X
- X# define IDISTNORM 8 /* was 17 - dgk */
- X# define IDISTAGGR 20 /* was 40 - dgk */
- X
- Xstatic short w1[9],w1x[9],w1y[9];
- Xstatic int tmp1,tmp2,tmp3,tmp4,distance;
- X
- X/* list of monsters to move */
- Xstatic struct foo { char x ; char y; char smart; } movelist[250] ;
- X
- X/*
- X * movemonst() Routine to move the monsters toward the player
- X *
- X * This routine has the responsibility to determine which monsters are to
- X * move, and call movemt() to do the move.
- X * Returns no value.
- X */
- Xvoid movemonst()
- X {
- X register int i,j,movecnt=0, smart_count, min_int ;
- X
- X if (c[TIMESTOP]) return; /* no action if time is stopped */
- X if (c[HASTESELF]) if ((c[HASTESELF]&1)==0) return;
- X if (spheres) movsphere(); /* move the spheres of annihilation if any */
- X if (c[HOLDMONST]) return; /* no action if monsters are held */
- X
- X if (c[AGGRAVATE]) /* determine window of monsters to move */
- X {
- X tmp1=playery-5; tmp2=playery+6; tmp3=playerx-10; tmp4=playerx+11;
- X distance=IDISTAGGR; /* depth of intelligent monster movement */
- X }
- X else
- X {
- X tmp1=playery-3; tmp2=playery+4; tmp3=playerx-5; tmp4=playerx+6;
- X distance=IDISTNORM; /* depth of intelligent monster movement */
- X }
- X
- X if (level == 0) /* if on outside level monsters can move in perimeter */
- X {
- X if (tmp1 < 0) tmp1=0; if (tmp2 > MAXY) tmp2=MAXY;
- X if (tmp3 < 0) tmp3=0; if (tmp4 > MAXX) tmp4=MAXX;
- X }
- X else /* if in a dungeon monsters can't be on the perimeter (wall there) */
- X {
- X if (tmp1 < 1) tmp1=1; if (tmp2 > MAXY-1) tmp2=MAXY-1;
- X if (tmp3 < 1) tmp3=1; if (tmp4 > MAXX-1) tmp4=MAXX-1;
- X }
- X
- X /* We now have a window in which to move monsters. First find all
- X monsters in the window, then decide whether or not to move them.
- X Its faster that way since the size of the window is usually larger
- X than the # of monsters in that window.
- X
- X Find all monsters in the window. The only time a monster cannot
- X move is if: monsters are not aggrevated, AND player is stealthed,
- X AND the monster is asleep due to stealth. Split into two
- X separate loops in order to simplify the if statement inside the
- X loop for the most common case.
- X
- X Also count # of smart monsters.
- X */
- X smart_count = 0 ;
- X min_int = 10 - c[HARDGAME] ; /* minimum monster intelligence to move smart */
- X if ( c[AGGRAVATE] || !c[STEALTH] )
- X {
- X for ( j = tmp1 ; j < tmp2 ; j++ )
- X for ( i = tmp3 ; i < tmp4 ; i++ )
- X if (mitem[i][j])
- X {
- X movelist[movecnt].x = i;
- X movelist[movecnt].y = j ;
- X if ( monster[mitem[i][j]].intelligence > min_int )
- X {
- X movelist[movecnt].smart = TRUE ;
- X smart_count++;
- X }
- X else
- X movelist[movecnt].smart = FALSE ;
- X movecnt++;
- X }
- X }
- X else
- X {
- X for ( j = tmp1; j < tmp2 ; j++ )
- X for ( i = tmp3 ; i < tmp4 ; i++ )
- X if ( mitem[i][j] && stealth[i][j] ) /* stealth[x][y] = 1 when AWAKE! */
- X {
- X movelist[movecnt].x = i;
- X movelist[movecnt].y = j ;
- X if ( monster[mitem[i][j]].intelligence > min_int )
- X {
- X movelist[movecnt].smart = TRUE ;
- X smart_count++;
- X }
- X else
- X movelist[movecnt].smart = FALSE ;
- X movecnt++;
- X }
- X }
- X
- X /* now move the monsters in the movelist. If we have at least one
- X smart monster, build a proximity ripple and use it for all smart
- X monster movement.
- X */
- X if (movecnt > 0 )
- X {
- X if ( c[SCAREMONST] )
- X for ( i = 0 ; i < movecnt ; i++ )
- X move_scared( movelist[i].x, movelist[i].y );
- X else
- X {
- X if ( smart_count > 0 )
- X {
- X /* I was going to put in code that prevented the rebuilding
- X of the proximity ripple if the player had not moved since
- X the last turn. Unfortunately, this permits the player to
- X blast down doors to treasure rooms and not have a single
- X intelligent monster move.
- X */
- X build_proximity_ripple();
- X for ( i = 0 ; i < movecnt ; i++ )
- X if ( movelist[i].smart )
- X move_smart( movelist[i].x, movelist[i].y );
- X else
- X move_dumb( movelist[i].x, movelist[i].y );
- X }
- X else
- X for ( i = 0 ; i < movecnt ; i++ )
- X move_dumb( movelist[i].x, movelist[i].y );
- X }
- X }
- X
- X /* Also check for the last monster hit. This is necessary to prevent
- X the player from getting free hits on a monster with long range
- X spells or when stealthed.
- X */
- X if ( c[AGGRAVATE] || !c[STEALTH] )
- X {
- X /* If the last monster hit is within the move window, its already
- X been moved.
- X */
- X if ( ( ( lasthx < tmp3 || lasthx >= tmp4 ) ||
- X ( lasthy < tmp1 || lasthy >= tmp2 ) ) &&
- X mitem[lasthx][lasthy] )
- X {
- X if ( c[SCAREMONST] )
- X move_scared( lasthx, lasthy );
- X else
- X if ( monster[mitem[lasthx][lasthy]].intelligence > min_int )
- X {
- X if ( smart_count == 0 )
- X build_proximity_ripple( );
- X move_smart( lasthx, lasthy );
- X }
- X else
- X move_dumb( lasthx, lasthy );
- X lasthx = w1x[0]; /* make sure the monster gets moved again */
- X lasthy = w1y[0];
- X }
- X }
- X else
- X {
- X /* If the last monster hit is within the move window, and not
- X asleep due to stealth, then it has already been moved.
- X Otherwise (monster outside window, asleep due to stealth),
- X move the monster and update the lasthit x,y position.
- X */
- X if ( ( lasthx < tmp3 || lasthx >= tmp4 ) ||
- X ( lasthy < tmp1 || lasthy >= tmp2 ) &&
- X mitem[lasthx][lasthy] || !stealth[lasthx][lasthy] )
- X {
- X if ( c[SCAREMONST] )
- X move_scared( lasthx, lasthy );
- X else
- X if ( monster[mitem[lasthx][lasthy]].intelligence > min_int )
- X {
- X if ( smart_count == 0 )
- X build_proximity_ripple( );
- X move_smart( lasthx, lasthy );
- X }
- X else
- X move_dumb( lasthx, lasthy );
- X lasthx = w1x[0]; /* make sure the monster gets moved again */
- X lasthy = w1y[0];
- X }
- X }
- X }
- X
- Xstatic char screen[MAXX][MAXY]; /* proximity ripple storage */
- X
- X/* queue for breadth-first 'search' build of proximity ripple.
- X*/
- X#define MAX_QUEUE 100
- X struct queue_entry
- X {
- X char x ;
- X char y ;
- X char distance ;
- X } queue[MAX_QUEUE];
- X int queue_head = 0 ;
- X int queue_tail = 0 ;
- X
- X/* put a location on the proximity ripple queue
- X*/
- X#define PUTQUEUE( _x, _y, _d ) \
- X { \
- X queue[queue_tail].x = (_x) ; \
- X queue[queue_tail].y = (_y) ; \
- X queue[queue_tail].distance = (_d); \
- X queue_tail++; \
- X if (queue_tail == MAX_QUEUE) \
- X queue_tail = 0 ; \
- X }
- X
- X/* take a location from the proximity ripple queue
- X*/
- X#define GETQUEUE( _x, _y, _d ) \
- X { \
- X (_x) = queue[queue_head].x ; \
- X (_y) = queue[queue_head].y ; \
- X (_d) = queue[queue_head].distance ; \
- X queue_head++; \
- X if (queue_head == MAX_QUEUE) \
- X queue_head = 0 ; \
- X }
- X
- X/* check for the proximity ripple queue being empty
- X*/
- X#define QUEUEEMPTY() (queue_head == queue_tail)
- X
- X/*
- X For smart monster movement, build a proximity ripple from the player's
- X position, out to a 'distance' of 20. For example:
- X
- X W 5 4 4 W W X Player is at position marked 1
- X W 5 W 3 3 W W W is a wall. Monsters will attempt
- X W 6 W 2 W 4 W to move to a location with a smaller
- X W 7 W 1 W 5 W value than their current position.
- X W 8 W W W 6 W Note that a monster at location X
- X W 9 9 8 7 7 7 will not move at all.
- X W W W 8 W W W
- X*/
- Xvoid build_proximity_ripple()
- X {
- X int xl, yl, xh, yh ;
- X int k, m, z, tmpx, tmpy;
- X int curx, cury, curdist;
- X
- X xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2;
- X vxy(&xl,&yl); vxy(&xh,&yh);
- X for (k=yl; k<=yh; k++)
- X for (m=xl; m<=xh; m++)
- X {
- X switch(item[m][k])
- X {
- X case OWALL:
- X case OPIT:
- X case OTRAPARROW:
- X case ODARTRAP:
- X case OCLOSEDDOOR:
- X case OTRAPDOOR:
- X case OTELEPORTER:
- X screen[m][k]=127;
- X break;
- X default:
- X screen[m][k] = 0;
- X break;
- X };
- X }
- X screen[playerx][playery]=1;
- X
- X/* now perform proximity ripple from playerx,playery to monster */
- X xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1;
- X vxy(&xl,&yl); vxy(&xh,&yh);
- X
- X PUTQUEUE( playerx, playery, 1 );
- X do
- X {
- X GETQUEUE( curx, cury, curdist );
- X
- X /* test all spots around the current one being looked at.
- X */
- X if ( ( curx >= xl && curx < xh ) &&
- X ( cury >= yl && cury < yh ) )
- X {
- X for (z=1; z<9; z++)
- X {
- X tmpx = curx + diroffx[z] ;
- X tmpy = cury + diroffy[z] ;
- X if (screen[tmpx][tmpy] == 0 )
- X {
- X screen[tmpx][tmpy] = curdist + 1;
- X PUTQUEUE( tmpx, tmpy, curdist + 1 );
- X }
- X }
- X }
- X }
- X while (!QUEUEEMPTY());
- X
- X }
- X
- X/*
- X Move scared monsters randomly away from the player position.
- X*/
- Xvoid move_scared( i, j )
- Xint i, j ;
- X {
- X int xl, yl, tmp, tmpitem ;
- X
- X /* check for a half-speed monster, and check if not to move. Could be
- X done in the monster list build.
- X */
- X switch(mitem[i][j])
- X {
- X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART:
- X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return;
- X };
- X
- X if ((xl = i+rnd(3)-2) < 0)
- X xl=0;
- X if (xl >= MAXX)
- X xl=MAXX-1;
- X if ((yl = j+rnd(3)-2) < 0)
- X yl=0;
- X if (yl >= MAXY)
- X yl=MAXY-1;
- X
- X if ((tmp=item[xl][yl]) != OWALL)
- X if (mitem[xl][yl] == 0)
- X if ((mitem[i][j] != VAMPIRE) || (tmp != OMIRROR))
- X if (tmp != OCLOSEDDOOR)
- X mmove(i,j,xl,yl);
- X }
- X
- X/*
- X Move monsters that are moving intelligently, using the proximity
- X ripple. Attempt to move to a position in the proximity ripple
- X that is closer to the player.
- X
- X Parameters: the X,Y position of the monster to be moved.
- X*/
- Xvoid move_smart( i, j )
- Xint i,j ;
- X {
- X int x,y,z ;
- X
- X /* check for a half-speed monster, and check if not to move. Could be
- X done in the monster list build.
- X */
- X switch(mitem[i][j])
- X {
- X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART:
- X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return;
- X };
- X
- X /* find an adjoining location in the proximity ripple that is
- X closer to the player (has a lower value) than the monster's
- X current position.
- X */
- X if (mitem[i][j] != VAMPIRE)
- X for (z=1; z<9; z++) /* go around in a circle */
- X {
- X x = i + diroffx[z] ;
- X y = j + diroffy[z] ;
- X if ( screen[x][y] < screen[i][j] )
- X if ( !mitem[x][y] )
- X {
- X mmove(i,j,w1x[0]=x,w1y[0]=y);
- X return;
- X }
- X }
- X else
- X /* prevent vampires from moving onto mirrors
- X */
- X for (z=1; z<9; z++) /* go around in a circle */
- X {
- X x = i + diroffx[z] ;
- X y = j + diroffy[z] ;
- X if (( screen[x][y] < screen[i][j] ) &&
- X ( item[x][y] != OMIRROR ))
- X if ( !mitem[x][y] )
- X {
- X mmove(i,j,w1x[0]=x,w1y[0]=y);
- X return;
- X }
- X }
- X
- X }
- X
- X/*
- X For monsters that are not moving in an intelligent fashion. Move
- X in a direct fashion toward the player's current position.
- X
- X Parameters: the X,Y position of the monster to move.
- X*/
- Xvoid move_dumb( i, j )
- Xint i, j ;
- X {
- X int xl, yl, xh, yh ;
- X int k, m, tmp, tmpd, tmpx, tmpy ;
- X
- X /* check for a half-speed monster, and check if not to move. Could be
- X done in the monster list build.
- X */
- X switch(mitem[i][j])
- X {
- X case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART:
- X case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return;
- X };
- X
- X /* dumb monsters move here */
- X /* set up range of spots to check. instead of checking all points
- X around the monster, only check those closest to the player. For
- X example, if the player is up and right of the monster, check only
- X the three spots up and right of the monster.
- X */
- X xl=i-1; yl=j-1; xh=i+2; yh=j+2;
- X if (i<playerx) xl++; else if (i>playerx) --xh;
- X if (j<playery) yl++; else if (j>playery) --yh;
- X
- X /* check all spots in the range. find the one that is closest to
- X the player. if the monster is already next to the player, exit
- X the check immediately.
- X */
- X tmpd = 10000 ;
- X tmpx = i ; tmpy = j ;
- X for ( k = xl ; k < xh ; k++ )
- X for ( m = yl ; m < yh ; m++ )
- X if ( k == playerx && m == playery )
- X {
- X tmpd = 1 ;
- X tmpx = k ;
- X tmpy = m ;
- X break; /* exitloop */
- X }
- X else if ((item[k][m] != OWALL) &&
- X (item[k][m] != OCLOSEDDOOR) &&
- X ((mitem[k][m] == 0 ) || (( k == i ) && ( m == j ))) &&
- X ((mitem[i][j] != VAMPIRE) || (item[k][m] != OMIRROR)))
- X {
- X tmp = (playerx-k)*(playerx-k)+(playery-m)*(playery-m);
- X if (tmp < tmpd)
- X {
- X tmpd = tmp;
- X tmpx = k;
- X tmpy = m;
- X } /* end if */
- X } /* end if */
- X
- X /* we have finished checking the spaces around the monster. if
- X any can be moved on and are closer to the player than the
- X current location, move the monster.
- X */
- X if ((tmpd < 10000) && ((tmpx != i) || (tmpy != j)))
- X {
- X mmove( i, j, tmpx, tmpy );
- X w1x[0] = tmpx ; /* for last monster hit */
- X w1y[0] = tmpy ;
- X }
- X else
- X {
- X w1x[0] = i ; /* for last monster hit */
- X w1y[0] = j ;
- X }
- X } /* end move_dumb() */
- X
- X/*
- X * mmove(x,y,xd,yd) Function to actually perform the monster movement
- X * int x,y,xd,yd;
- X *
- X * Enter with the from coordinates in (x,y) and the destination coordinates
- X * in (xd,yd).
- X */
- Xvoid mmove(aa,bb,cc,dd)
- X int aa,bb,cc,dd;
- X {
- X register int tmp,i,flag;
- X char *who,*p;
- X flag=0; /* set to 1 if monster hit by arrow trap */
- X if ((cc==playerx) && (dd==playery))
- X {
- X hitplayer(aa,bb);
- X return;
- X }
- X i=item[cc][dd];
- X if ((i==OPIT) || (i==OTRAPDOOR))
- X switch(mitem[aa][bb])
- X {
- X case BAT: case EYE:
- X case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH:
- X case VAMPIRE: case SILVERDRAGON: case POLTERGEIST:
- X case DEMONLORD: case DEMONLORD+1: case DEMONLORD+2:
- X case DEMONLORD+3: case DEMONLORD+4: case DEMONLORD+5:
- X case DEMONLORD+6: case DEMONPRINCE: break;
- X
- X default: mitem[aa][bb]=0; /* fell in a pit or trapdoor */
- X };
- X tmp = mitem[aa][bb];
- X mitem[cc][dd] = tmp;
- X if (i==OANNIHILATION)
- X {
- X if (tmp>=DEMONLORD+3) /* demons dispel spheres */
- X {
- X cursors();
- X lprintf("\nThe %s dispels the sphere!",monster[tmp].name);
- X rmsphere(cc,dd); /* delete the sphere */
- X }
- X else mitem[cc][dd]=i=tmp=0;
- X }
- X stealth[cc][dd]=1;
- X if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd]=1;
- X mitem[aa][bb] = 0;
- X if (tmp == LEPRECHAUN)
- X switch(i)
- X {
- X case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD:
- X case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
- X item[cc][dd] = 0; /* leprechaun takes gold */
- X };
- X
- X if (tmp == TROLL) /* if a troll regenerate him */
- X if ((gtime & 1) == 0)
- X if (monster[tmp].hitpoints > hitp[cc][dd]) hitp[cc][dd]++;
- X
- X if (i==OTRAPARROW) /* arrow hits monster */
- X { who = "An arrow"; if ((hitp[cc][dd] -= rnd(10)+level) <= 0)
- X { mitem[cc][dd]=0; flag=2; } else flag=1; }
- X if (i==ODARTRAP) /* dart hits monster */
- X { who = "A dart"; if ((hitp[cc][dd] -= rnd(6)) <= 0)
- X { mitem[cc][dd]=0; flag=2; } else flag=1; }
- X if (i==OTELEPORTER) /* monster hits teleport trap */
- X { flag=3; fillmonst(mitem[cc][dd]); mitem[cc][dd]=0; }
- X if (c[BLINDCOUNT]) return; /* if blind don't show where monsters are */
- X# ifdef DGK
- X if (know[cc][dd] & HAVESEEN)
- X# else
- X if (know[cc][dd] & 1)
- X# endif
- X {
- X p=0;
- X if (flag) cursors();
- X switch(flag)
- X {
- X case 1: p="\n%s hits the %s"; break;
- X case 2: p="\n%s hits and kills the %s"; break;
- X case 3: p="\nThe %s%s gets teleported"; who=""; break;
- X };
- X if (p) { lprintf(p,who,monster[tmp].name); beep(); }
- X }
- X/* if (yrepcount>1) { know[aa][bb] &= 2; know[cc][dd] &= 2; return; } */
- X# ifdef DGK
- X if (know[aa][bb] & HAVESEEN) show1cell(aa,bb);
- X if (know[cc][dd] & HAVESEEN) show1cell(cc,dd);
- X# else
- X if (know[aa][bb] & 1) show1cell(aa,bb);
- X if (know[cc][dd] & 1) show1cell(cc,dd);
- X# endif
- X }
- END_OF_FILE
- if test 18818 -ne `wc -c <'movem.c'`; then
- echo shar: \"'movem.c'\" unpacked with wrong size!
- fi
- # end of 'movem.c'
- fi
- if test -f 'savelev.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'savelev.c'\"
- else
- echo shar: Extracting \"'savelev.c'\" \(3594 characters\)
- sed "s/^X//" >'savelev.c' <<'END_OF_FILE'
- X/* savelev.c Larn is copyrighted 1986 by Noah Morgan. */
- X#include "header.h"
- X
- X# ifdef MSDOS
- X
- Xextern int swapfd; /* swap file file descriptor */
- X
- X
- XDISKBLOCK *
- Xgetfreediskblk()
- X{
- X DISKBLOCK *dp;
- X
- X for (dp = diskblks; dp; dp = dp->next)
- X if (dp->level == FREEBLOCK)
- X return dp;
- X levelinfo();
- X error("Can't find a free disk block ?\n");
- X}
- X
- XRAMBLOCK *
- Xgetramblk(lev)
- X{
- X RAMBLOCK *rp, *orp;
- X DISKBLOCK *dp;
- X long otime;
- X unsigned int bytes;
- X
- X /* Check if the level is in memory already.
- X */
- X for (rp = ramblks; rp; rp = rp->next)
- X if (rp->level == lev)
- X return rp;
- X
- X /* Else grab the first available one.
- X */
- X for (rp = ramblks; rp; rp = rp->next)
- X if (rp->level == FREEBLOCK)
- X return rp;
- X
- X /* No ramblocks free, so swap out the oldest level
- X */
- X dp = getfreediskblk();
- X
- X# ifdef ndef
- Xwarn("\nTrying to swap\n");
- X# endif
- X
- X /* Find the oldest level for swapping out.
- X */
- X otime = ramblks->gtime;
- X orp = ramblks;
- X for (rp = ramblks->next; rp; rp = rp->next) {
- X if (rp->gtime < otime) {
- X otime = rp->gtime;
- X orp = rp;
- X }
- X }
- X
- X /* Send the oldest level out to disk.
- X */
- X if (lseek(swapfd, dp->fpos, 0) < 0)
- X error("Can't seek to %ld\n", dp->fpos);
- X
- X bytes = sizeof rp->cell;
- X if (write(swapfd, (char *) orp->cell, bytes) != bytes)
- X error("Out of space writing swap file !\n");
- X
- X /* Update the level information
- X */
- X dp->level = orp->level;
- X dp->gtime = orp->gtime;
- X orp->level = FREEBLOCK;
- X# ifdef ndef
- Xwarn("Successful swap\n");
- X# endif
- X return orp;
- X}
- X
- X
- X# endif
- X
- X/*
- X * routine to save the present level into storage
- X */
- Xsavelevel()
- X {
- X register struct cel *pcel;
- X register char *pitem,*pknow,*pmitem;
- X register short *phitp,*piarg;
- X register struct cel *pecel;
- X
- X# ifdef MSDOS
- X RAMBLOCK *rp;
- X
- X rp = getramblk(level);
- X pcel = rp->cell;
- X rp->gtime = gtime;
- X rp->level = level;
- X# else
- X pcel = &cell[level*MAXX*MAXY]; /* pointer to this level's cells */
- X# endif
- X pecel = pcel + MAXX*MAXY; /* pointer to past end of this level's cells */
- X pitem=item[0]; piarg=iarg[0]; pknow=know[0]; pmitem=mitem[0]; phitp=hitp[0];
- X while (pcel < pecel)
- X {
- X pcel->mitem = *pmitem++;
- X pcel->hitp = *phitp++;
- X pcel->item = *pitem++;
- X pcel->know = *pknow++;
- X pcel->iarg = *piarg++;
- X pcel++;
- X }
- X }
- X
- X
- X/*
- X * routine to restore a level from storage
- X */
- Xgetlevel()
- X {
- X register struct cel *pcel;
- X register char *pitem,*pknow,*pmitem;
- X register short *phitp,*piarg;
- X register struct cel *pecel;
- X
- X# ifdef MSDOS
- X RAMBLOCK *rp;
- X DISKBLOCK *dp;
- X unsigned int bytes;
- X
- X /* Is the level in memory already ?
- X */
- X for (rp = ramblks; rp; rp = rp->next)
- X if (rp->level == level)
- X goto haverp;
- X
- X /* Is it on disk ?
- X */
- X for (dp = diskblks; dp; dp = dp->next)
- X if (dp->level == level)
- X break;
- X if (dp == NULL) {
- X levelinfo();
- X error("Level %d is neither in memory nor on disk\n", level);
- X }
- X
- X /* Make room for it and read it in.
- X */
- X rp = getramblk(level);
- X if (lseek(swapfd, dp->fpos, 0) < 0)
- X error("Can't seek to %ld\n", dp->fpos);
- X bytes = sizeof rp->cell;
- X if (read(swapfd, (char *) rp->cell, bytes) != bytes)
- X error("Didn't read %u bytes\n", bytes);
- X
- X /* The disk space is available for future swaps.
- X */
- X dp->level = FREEBLOCK;
- Xhaverp:
- X pcel = rp->cell;
- X rp->level = FREEBLOCK;
- X# else
- X pcel = &cell[level*MAXX*MAXY]; /* pointer to this level's cells */
- X# endif
- X pecel = pcel + MAXX*MAXY; /* pointer to past end of this level's cells */
- X pitem=item[0]; piarg=iarg[0]; pknow=know[0]; pmitem=mitem[0]; phitp=hitp[0];
- X while (pcel < pecel)
- X {
- X *pmitem++ = pcel->mitem;
- X *phitp++ = pcel->hitp;
- X *pitem++ = pcel->item;
- X *pknow++ = pcel->know;
- X *piarg++ = pcel->iarg;
- X pcel++;
- X }
- X }
- END_OF_FILE
- if test 3594 -ne `wc -c <'savelev.c'`; then
- echo shar: \"'savelev.c'\" unpacked with wrong size!
- fi
- # end of 'savelev.c'
- fi
- if test -f 'spells.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'spells.c'\"
- else
- echo shar: Extracting \"'spells.c'\" \(27476 characters\)
- sed "s/^X//" >'spells.c' <<'END_OF_FILE'
- X/*
- X cast() Subroutine called by parse to cast a spell for the user
- X speldamage(x) Function to perform spell functions cast by the player
- X loseint() Routine to decrement your int (intelligence) if > 3
- X isconfuse() Routine to check to see if player is confused
- X nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster
- X fullhit(xx) Function to return full damage against a monst (aka web)
- X direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir
- X godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks
- X ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt
- X tdirect(spnum) Routine to teleport away a monster
- X omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player
- X dirsub(x,y) Routine to ask for direction, then modify x,y for it
- X dirpoly(spnum) Routine to ask for a direction and polymorph a monst
- X annihilate() Routine to annihilate monsters around player, playerx,playery
- X genmonst() Function to ask for monster and genocide from game
- X*/
- X
- X#include "header.h"
- X#include <ctype.h>
- X
- X#define min(x,y) (((x)>(y))?(y):(x))
- X#define max(x,y) (((x)>(y))?(x):(y))
- X
- Xstruct isave /* used for altar reality */
- X {
- X char type; /* 0=item, 1=monster */
- X char id; /* item number or monster number */
- X short arg; /* the type of item or hitpoints of monster */
- X };
- X
- X/* Forward declarations
- X*/
- Xstatic void create_guardian();
- Xextern hitm();
- X
- X/*
- X * cast() Subroutine called by parse to cast a spell for the user
- X *
- X * No arguments and no return value.
- X */
- Xstatic char eys[] = "\nEnter your spell: ";
- Xcast()
- X {
- X register int i,j,a,b,d;
- X cursors();
- X if (c[SPELLS]<=0)
- X {
- X lprcat("\nYou don't have any spells!");
- X return;
- X }
- X lprcat(eys);
- X --c[SPELLS];
- X while ((a=ttgetch())=='I')
- X {
- X seemagic(-1);
- X cursors();
- X lprcat(eys);
- X }
- X if (a=='\33')
- X goto over; /* to escape casting a spell */
- X if ((b=ttgetch())=='\33')
- X goto over; /* to escape casting a spell */
- X if ((d=ttgetch())=='\33')
- X {
- Xover:
- X lprcat(aborted);
- X c[SPELLS]++;
- X return;
- X } /* to escape casting a spell */
- X#ifdef EXTRA
- X c[SPELLSCAST]++;
- X#endif
- X for (lprc('\n'),j= -1,i=0; i<SPNUM; i++) /*seq search for his spell, hash?*/
- X if ((spelcode[i][0]==a) && (spelcode[i][1]==b) && (spelcode[i][2]==d))
- X if (spelknow[i])
- X { speldamage(i); j = 1; i=SPNUM; }
- X
- X if (j == -1) lprcat(" Nothing Happened ");
- X bottomline();
- X }
- X
- X/*
- X * speldamage(x) Function to perform spell functions cast by the player
- X * int x;
- X *
- X * Enter with the spell number, returns no value.
- X * Please insure that there are 2 spaces before all messages here
- X */
- Xstatic speldamage(x)
- X int x;
- X {
- X register int i,j,clev;
- X int xl,xh,yl,yh;
- X register char *p,*kn,*pm;
- X
- X if (x>=SPNUM) return; /* no such spell */
- X if (c[TIMESTOP]) { lprcat(" It didn't seem to work"); return; } /* not if time stopped */
- X clev = c[LEVEL];
- X if ((rnd(23)==7) || (rnd(18) > c[INTELLIGENCE]))
- X { lprcat(" It didn't work!"); return; }
- X if (clev*3+2 < x)
- X {
- X lprcat(" Nothing happens. You seem inexperienced at this");
- X return;
- X }
- X
- X switch(x)
- X {
- X/* ----- LEVEL 1 SPELLS ----- */
- X
- X case 0: if (c[PROTECTIONTIME]==0) c[MOREDEFENSES]+=2; /* protection field +2 */
- X c[PROTECTIONTIME] += 250; return;
- X
- X case 1: i = rnd(((clev+1)<<1)) + clev + 3;
- X godirect(x,i,(clev>=2)?" Your missiles hit the %s":" Your missile hit the %s",100,'+'); /* magic missile */
- X
- X return;
- X
- X case 2: if (c[DEXCOUNT]==0) c[DEXTERITY]+=3; /* dexterity */
- X c[DEXCOUNT] += 400; return;
- X
- X case 3: i=rnd(3)+1;
- X p=" While the %s slept, you smashed it %d times";
- X ws: direct(x,fullhit(i),p,i); /* sleep */ return;
- X
- X case 4: /* charm monster */ c[CHARMCOUNT] += c[CHARISMA]<<1; return;
- X
- X case 5: godirect(x,rnd(10)+15+clev," The sound damages the %s",70,'@'); /* sonic spear */
- X return;
- X
- X/* ----- LEVEL 2 SPELLS ----- */
- X
- X case 6: i=rnd(3)+2; p=" While the %s is entangled, you hit %d times";
- X goto ws; /* web */
- X
- X case 7: if (c[STRCOUNT]==0) c[STREXTRA]+=3; /* strength */
- X c[STRCOUNT] += 150+rnd(100); return;
- X
- X case 8: yl = playery-5; /* enlightenment */
- X yh = playery+6; xl = playerx-15; xh = playerx+16;
- X vxy(&xl,&yl); vxy(&xh,&yh); /* check bounds */
- X for (i=yl; i<=yh; i++) /* enlightenment */
- X# ifdef DGK
- X for (j=xl; j<=xh; j++)
- X know[j][i]=KNOWALL;
- X# else
- X for (j=xl; j<=xh; j++) know[j][i]=1;
- X# endif
- X draws(xl,xh+1,yl,yh+1); return;
- X
- X case 9: raisehp(20+(clev<<1)); return; /* healing */
- X
- X case 10: c[BLINDCOUNT]=0; return; /* cure blindness */
- X
- X case 11: createmonster(makemonst(level+1)+8); return;
- X
- X case 12: if (rnd(11)+7 <= c[WISDOM]) direct(x,rnd(20)+20+clev," The %s believed!",0);
- X else lprcat(" It didn't believe the illusions!");
- X return;
- X
- X case 13: /* if he has the amulet of invisibility then add more time */
- X for (j=i=0; i<26; i++)
- X if (iven[i]==OAMULET) j+= 1+ivenarg[i];
- X c[INVISIBILITY] += (j<<7)+12; return;
- X
- X/* ----- LEVEL 3 SPELLS ----- */
- X
- X case 14: godirect(x,rnd(25+clev)+25+clev," The fireball hits the %s",40,'*'); return; /* fireball */
- X
- X case 15: godirect(x,rnd(25)+20+clev," Your cone of cold strikes the %s",60,'O'); /* cold */
- X return;
- X
- X case 16: dirpoly(x); return; /* polymorph */
- X
- X case 17: c[CANCELLATION]+= 5+clev; return; /* cancellation */
- X
- X case 18: c[HASTESELF]+= 7+clev; return; /* haste self */
- X
- X case 19: omnidirect(x,30+rnd(10)," The %s gasps for air"); /* cloud kill */
- X return;
- X
- X case 20: xh = min(playerx+1,MAXX-2); yh = min(playery+1,MAXY-2);
- X for (i=max(playerx-1,1); i<=xh; i++) /* vaporize rock */
- X for (j=max(playery-1,1); j<=yh; j++)
- X {
- X kn = &know[i][j];
- X pm = &mitem[i][j];
- X switch(*(p= &item[i][j]))
- X {
- X case OWALL: if (level < MAXLEVEL+MAXVLEVEL-1)
- X *p = *kn = 0;
- X break;
- X
- X case OSTATUE: if (c[HARDGAME]<3)
- X {
- X *p=OBOOK; iarg[i][j]=level; *kn=0;
- X }
- X break;
- X
- X case OTHRONE:
- X *p= OTHRONE2;
- X create_guardian( GNOMEKING, i, j );
- X break;
- X
- X case OALTAR:
- X create_guardian( DEMONPRINCE, i, j );
- X break;
- X
- X case OFOUNTAIN:
- X create_guardian( WATERLORD, i, j );
- X break;
- X };
- X switch(*pm)
- X {
- X case XORN: ifblind(i,j); hitm(i,j,200); break; /* Xorn takes damage from vpr */
- X }
- X }
- X return;
- X
- X/* ----- LEVEL 4 SPELLS ----- */
- X
- X case 21: direct(x,100+clev," The %s shrivels up",0); /* dehydration */
- X return;
- X
- X case 22: godirect(x,rnd(25)+20+(clev<<1)," A lightning bolt hits the %s",1,'~'); /* lightning */
- X return;
- X
- X case 23: i=min(c[HP]-1,c[HPMAX]/2); /* drain life */
- X direct(x,i+i,"",0); c[HP] -= i; return;
- X
- X case 24: if (c[GLOBE]==0) c[MOREDEFENSES] += 10;
- X c[GLOBE] += 200; loseint(); /* globe of invulnerability */
- X return;
- X
- X case 25: omnidirect(x,32+clev," The %s struggles for air in your flood!"); /* flood */
- X return;
- X
- X case 26: if (rnd(151)==63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000); died(270); return; }
- X if (c[WISDOM]>rnd(10)+10) direct(x,2000," The %s's heart stopped",0); /* finger of death */
- X else lprcat(" It didn't work"); return;
- X
- X/* ----- LEVEL 5 SPELLS ----- */
- X
- X case 27: c[SCAREMONST] += rnd(10)+clev; return; /* scare monster */
- X
- X case 28: c[HOLDMONST] += rnd(10)+clev; return; /* hold monster */
- X
- X case 29: c[TIMESTOP] += rnd(20)+(clev<<1); return; /* time stop */
- X
- X case 30: tdirect(x); return; /* teleport away */
- X
- X case 31: omnidirect(x,35+rnd(10)+clev," The %s cringes from the flame"); /* magic fire */
- X return;
- X
- X/* ----- LEVEL 6 SPELLS ----- */
- X
- X case 32: if ((rnd(23)==5) && (wizard==0)) /* sphere of annihilation */
- X {
- X beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n");
- X nap(4000); died(258); return;
- X }
- X xl=playerx; yl=playery;
- X loseint();
- X i=dirsub(&xl,&yl); /* get direction of sphere */
- X newsphere(xl,yl,i,rnd(20)+11); /* make a sphere */
- X return;
- X
- X case 33: genmonst(); spelknow[33]=0; /* genocide */
- X loseint();
- X return;
- X
- X case 34: /* summon demon */
- X if (rnd(100) > 30) { direct(x,150," The demon strikes at the %s",0); return; }
- X if (rnd(100) > 15) { lprcat(" Nothing seems to have happened"); return; }
- X lprcat(" The demon turned on you and vanished!"); beep();
- X i=rnd(40)+30; lastnum=277;
- X losehp(i); /* must say killed by a demon */ return;
- X
- X case 35: /* walk through walls */
- X c[WTW] += rnd(10)+5; return;
- X
- X case 36: /* alter reality */
- X {
- X struct isave *save; /* pointer to item save structure */
- X int sc; sc=0; /* # items saved */
- X save = (struct isave *)malloc(sizeof(struct isave)*MAXX*MAXY*2);
- X if (save == NULL)
- X {
- X lprcat("\nPolinneaus won't let you mess with his dungeon!");
- X return;
- X }
- X for (j=0; j<MAXY; j++)
- X for (i=0; i<MAXX; i++) /* save all items and monsters */
- X {
- X xl = item[i][j];
- X if (xl && xl!=OWALL && xl!=OANNIHILATION)
- X {
- X save[sc].type=0; save[sc].id=item[i][j];
- X save[sc++].arg=iarg[i][j];
- X }
- X if (mitem[i][j])
- X {
- X save[sc].type=1; save[sc].id=mitem[i][j];
- X save[sc++].arg=hitp[i][j];
- X }
- X item[i][j]=OWALL; mitem[i][j]=0;
- X# ifdef DGK
- X if (wizard)
- X know[i][j]=KNOWALL;
- X else
- X know[i][j]=0;
- X# else
- X if (wizard) know[i][j]=1; else know[i][j]=0;
- X# endif
- X }
- X eat(1,1); if (level==1) item[33][MAXY-1]=0;
- X for (j=rnd(MAXY-2), i=1; i<MAXX-1; i++) item[i][j]=0;
- X while (sc>0) /* put objects back in level */
- X {
- X --sc;
- X if (save[sc].type == 0)
- X {
- X int trys;
- X for (trys=100, i=j=1; --trys>0 && item[i][j]; i=rnd(MAXX-1), j=rnd(MAXY-1));
- X if (trys) { item[i][j]=save[sc].id; iarg[i][j]=save[sc].arg; }
- X }
- X else
- X { /* put monsters back in */
- X int trys;
- X for (trys=100, i=j=1; --trys>0 && (item[i][j]==OWALL || mitem[i][j]); i=rnd(MAXX-1), j=rnd(MAXY-1));
- X if (trys) { mitem[i][j]=save[sc].id; hitp[i][j]=save[sc].arg; }
- X }
- X }
- X loseint();
- X draws(0,MAXX,0,MAXY); if (wizard==0) spelknow[36]=0;
- X free((char*)save); positionplayer(); return;
- X }
- X
- X case 37: /* permanence */ adjtime(-99999L); spelknow[37]=0; /* forget */
- X loseint();
- X return;
- X
- X default: lprintf(" spell %d not available!",(long)x); beep(); return;
- X };
- X }
- X
- X/*
- X Create a guardian for a throne/altar/fountain, as a result of the player
- X using a VPR spell or pulverization scroll on it.
- X*/
- Xstatic void create_guardian( monst, x, y )
- Xint monst; /* monster code for the guardian */
- Xint x, y; /* coords of the object being guarded */
- X {
- X int k ;
- X
- X /* prevent the guardian from being created on top of the player
- X */
- X if ((x == playerx) && (y == playery))
- X {
- X k = rnd(8);
- X x += diroffx[k];
- X y += diroffy[k];
- X }
- X know[x][y] = 0;
- X mitem[x][y] = monst ;
- X hitp[x][y] = monster[monst].hitpoints;
- X }
- X
- X/*
- X * loseint() Routine to subtract 1 from your int (intelligence) if > 3
- X *
- X * No arguments and no return value
- X */
- Xstatic loseint()
- X {
- X if (--c[INTELLIGENCE]<3) c[INTELLIGENCE]=3;
- X }
- X
- X/*
- X * isconfuse() Routine to check to see if player is confused
- X *
- X * This routine prints out a message saying "You can't aim your magic!"
- X * returns 0 if not confused, non-zero (time remaining confused) if confused
- X */
- Xstatic isconfuse()
- X {
- X if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); }
- X return(c[CONFUSE]);
- X }
- X
- X/*
- X * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster
- X * int x,monst;
- X *
- X * Subroutine to return 1 if the spell can't affect the monster
- X * otherwise returns 0
- X * Enter with the spell number in x, and the monster number in monst.
- X */
- Xstatic nospell(x,monst)
- X int x,monst;
- X {
- X register int tmp;
- X if (x>=SPNUM || monst>=MAXMONST+8 || monst<0 || x<0) return(0); /* bad spell or monst */
- X if ((tmp=spelweird[monst-1][x])==0) return(0);
- X cursors(); lprc('\n'); lprintf(spelmes[tmp],monster[monst].name); return(1);
- X }
- X
- X/*
- X * fullhit(xx) Function to return full damage against a monster (aka web)
- X * int xx;
- X *
- X * Function to return hp damage to monster due to a number of full hits
- X * Enter with the number of full hits being done
- X */
- Xfullhit(xx)
- X int xx;
- X {
- X register int i;
- X if (xx<0 || xx>20) return(0); /* fullhits are out of range */
- X if (c[LANCEDEATH]) return(10000); /* lance of death */
- X i = xx * ((c[WCLASS]>>1)+c[STRENGTH]+c[STREXTRA]-c[HARDGAME]-12+c[MOREDAM]);
- X return( (i>=1) ? i : xx );
- X }
- X
- X/*
- X * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir
- X * int spnum,dam,arg;
- X * char *str;
- X *
- X * Routine to ask for a direction to a spell and then hit the monster
- X * Enter with the spell number in spnum, the damage to be done in dam,
- X * lprintf format string in str, and lprintf's argument in arg.
- X * Returns no value.
- X */
- Xstatic direct(spnum,dam,str,arg)
- X int spnum,dam,arg;
- X char *str;
- X {
- X extern char lastmonst[];
- X int x,y;
- X register int m;
- X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad arguments */
- X if (isconfuse()) return;
- X dirsub(&x,&y);
- X m = mitem[x][y];
- X if (item[x][y]==OMIRROR)
- X {
- X if (spnum==3) /* sleep */
- X {
- X lprcat("You fall asleep! "); beep();
- X fool:
- X arg += 2;
- X while (arg-- > 0) { parse2(); nap(1000); }
- X return;
- X }
- X else if (spnum==6) /* web */
- X {
- X lprcat("You get stuck in your own web! "); beep();
- X goto fool;
- X }
- X else
- X {
- X lastnum=278;
- X lprintf(str,"spell caster (thats you)",(long)arg);
- X beep(); losehp(dam); return;
- X }
- X }
- X if (m==0)
- X { lprcat(" There wasn't anything there!"); return; }
- X ifblind(x,y);
- X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; }
- X lprintf(str,lastmonst,(long)arg); hitm(x,y,dam);
- X }
- X
- X/*
- X * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks
- X * int spnum,dam,delay;
- X * char *str,cshow;
- X *
- X * Function to hit in a direction from a missile weapon and have it keep
- X * on going in that direction until its power is exhausted
- X * Enter with the spell number in spnum, the power of the weapon in hp,
- X * lprintf format string in str, the # of milliseconds to delay between
- X * locations in delay, and the character to represent the weapon in cshow.
- X * Returns no value.
- X */
- Xgodirect(spnum,dam,str,delay,cshow)
- X int spnum,dam,delay;
- X char *str,cshow;
- X {
- X extern char lastmonst[] ;
- X register char *p;
- X register int x,y,m;
- X int dx,dy;
- X if (spnum<0 || spnum>=SPNUM || str==0 || delay<0) return; /* bad args */
- X if (isconfuse()) return;
- X dirsub(&dx,&dy); x=dx; y=dy;
- X dx = x-playerx; dy = y-playery; x = playerx; y = playery;
- X while (dam>0)
- X {
- X x += dx; y += dy;
- X if ((x > MAXX-1) || (y > MAXY-1) || (x < 0) || (y < 0))
- X {
- X dam=0; break; /* out of bounds */
- X }
- X if ((x==playerx) && (y==playery)) /* if energy hits player */
- X {
- X cursors(); lprcat("\nYou are hit my your own magic!"); beep();
- X lastnum=278; losehp(dam); return;
- X }
- X if (c[BLINDCOUNT]==0) /* if not blind show effect */
- X {
- X cursor(x+1,y+1); lprc(cshow); nap(delay); show1cell(x,y);
- X }
- X if ((m=mitem[x][y])) /* is there a monster there? */
- X {
- X ifblind(x,y);
- X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; }
- X cursors(); lprc('\n');
- X lprintf(str,lastmonst); dam -= hitm(x,y,dam);
- X show1cell(x,y); nap(1000); x -= dx; y -= dy;
- X }
- X else switch (*(p= &item[x][y]))
- X {
- X case OWALL:
- X cursors();
- X lprc('\n');
- X lprintf(str,"wall");
- X if (dam>=50+c[HARDGAME]) /* enough damage? */
- X if (level<MAXLEVEL+MAXVLEVEL-1) /* not on V3 */
- X if ((x<MAXX-1) && (y<MAXY-1) && (x) && (y))
- X {
- X lprcat(" The wall crumbles");
- X *p=0;
- X know[x][y]=0;
- X show1cell(x,y);
- X }
- X dam = 0;
- X break;
- X
- X case OCLOSEDDOOR:
- X cursors();
- X lprc('\n');
- X lprintf(str,"door");
- X if (dam>=40)
- X {
- X lprcat(" The door is blasted apart");
- X *p = 0;
- X know[x][y] = 0;
- X show1cell( x, y );
- X }
- X dam = 0 ;
- X break;
- X
- X case OSTATUE:
- X cursors();
- X lprc('\n');
- X lprintf(str,"statue");
- X if (c[HARDGAME]<3)
- X if (dam>44)
- X {
- X lprcat(" The statue crumbles");
- X *p=OBOOK;
- X iarg[x][y]=level;
- X know[x][y] = 0;
- X show1cell( x, y );
- X }
- X dam = 0 ;
- X break;
- X
- X case OTHRONE:
- X cursors();
- X lprc('\n');
- X lprintf(str,"throne");
- X if (dam>39)
- X {
- X *p = OTHRONE2;
- X create_guardian( GNOMEKING, x, y );
- X show1cell( x, y );
- X }
- X dam = 0;
- X break;
- X
- X case OALTAR:
- X cursors();
- X lprc('\n');
- X lprintf(str, "altar");
- X if ( dam > 75 - ( c[HARDGAME] >> 2 ))
- X {
- X create_guardian( DEMONPRINCE, x, y );
- X show1cell( x, y );
- X }
- X dam = 0 ;
- X break;
- X
- X case OFOUNTAIN:
- X cursors();
- X lprc('\n');
- X lprintf(str, "fountain");
- X if ( dam > 55 )
- X {
- X create_guardian( WATERLORD, x, y );
- X show1cell( x, y );
- X }
- X dam = 0 ;
- X break;
- X
- X case OMIRROR:
- X {
- X int bounce = FALSE, odx=dx, ody=dy ;
- X /* spells may bounce directly back or off at an angle
- X */
- X if (rnd(100) < 50 )
- X {
- X bounce = TRUE ;
- X dx *= -1;
- X }
- X if (rnd(100) < 50 )
- X {
- X bounce = TRUE ;
- X dy *= -1;
- X }
- X if (!bounce || ((odx==dx) && (ody==dy))) /* guarentee a bounce */
- X {
- X dx = -odx;
- X dy = -ody;
- X }
- X }
- X break;
- X };
- X dam -= 3 + (c[HARDGAME]>>1);
- X }
- X }
- X
- X/*
- X * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt
- X * int x,y;
- X *
- X * Subroutine to copy the word "monster" into lastmonst if the player is blind
- X * Enter with the coordinates (x,y) of the monster
- X * Returns no value.
- X */
- Xifblind(x,y)
- X int x,y;
- X {
- X extern char lastmonst[] ;
- X char *p;
- X vxy(&x,&y); /* verify correct x,y coordinates */
- X if (c[BLINDCOUNT]) { lastnum=279; p="monster"; }
- X else { lastnum=mitem[x][y]; p=monster[lastnum].name; }
- X strcpy(lastmonst,p);
- X }
- X
- X/*
- X * tdirect(spnum) Routine to teleport away a monster
- X * int spnum;
- X *
- X * Routine to ask for a direction to a spell and then teleport away monster
- X * Enter with the spell number that wants to teleport away
- X * Returns no value.
- X */
- Xstatic tdirect(spnum)
- X int spnum;
- X {
- X int x,y;
- X register int m;
- X if (spnum<0 || spnum>=SPNUM) return; /* bad args */
- X if (isconfuse()) return;
- X dirsub(&x,&y);
- X if ((m=mitem[x][y])==0)
- X { lprcat(" There wasn't anything there!"); return; }
- X ifblind(x,y);
- X if (nospell(spnum,m)) { lasthx=x; lasthy=y; return; }
- X fillmonst(m); mitem[x][y]=0; know[x][y] &= ~KNOWHERE;
- X }
- X
- X/*
- X * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player
- X * int sp,dam;
- X * char *str;
- X *
- X * Routine to cast a spell and then hit the monster in all directions
- X * Enter with the spell number in sp, the damage done to wach square in dam,
- X * and the lprintf string to identify the spell in str.
- X * Returns no value.
- X */
- Xstatic omnidirect(spnum,dam,str)
- X int spnum,dam;
- X char *str;
- X {
- X extern char lastmonst[] ;
- X register int x,y,m;
- X if (spnum<0 || spnum>=SPNUM || str==0) return; /* bad args */
- X for (x=playerx-1; x<playerx+2; x++)
- X for (y=playery-1; y<playery+2; y++)
- X {
- X if (m=mitem[x][y])
- X if (nospell(spnum,m) == 0)
- X {
- X ifblind(x,y);
- X cursors(); lprc('\n'); lprintf(str,lastmonst);
- X hitm(x,y,dam); nap(800);
- X }
- X else { lasthx=x; lasthy=y; }
- X }
- X }
- X
- X/*
- X * dirsub(x,y) Routine to ask for direction, then modify playerx,
- X * playery for it
- X * int *x,*y;
- X *
- X * Function to ask for a direction and modify an x,y for that direction
- X * Enter with the coordinate destination (x,y).
- X * Returns index into diroffx[] (0-8).
- X */
- Xdirsub(x,y)
- X int *x,*y;
- X {
- X register int i;
- X lprcat("\nIn What Direction? ");
- X for (i=0; ; )
- X switch(ttgetch())
- X {
- X case 'b': i++;
- X case 'n': i++;
- X case 'y': i++;
- X case 'u': i++;
- X case 'h': i++;
- X case 'k': i++;
- X case 'l': i++;
- X case 'j': i++; goto out;
- X };
- Xout:
- X *x = playerx+diroffx[i]; *y = playery+diroffy[i];
- X vxy(x,y); return(i);
- X }
- X
- X/*
- X * dirpoly(spnum) Routine to ask for a direction and polymorph a monst
- X * int spnum;
- X *
- X * Subroutine to polymorph a monster and ask for the direction its in
- X * Enter with the spell number in spmun.
- X * Returns no value.
- X */
- Xstatic dirpoly(spnum)
- X int spnum;
- X {
- X int x,y,m;
- X if (spnum<0 || spnum>=SPNUM) return; /* bad args */
- X if (isconfuse()) return; /* if he is confused, he can't aim his magic */
- X dirsub(&x,&y);
- X if (mitem[x][y]==0)
- X { lprcat(" There wasn't anything there!"); return; }
- X ifblind(x,y);
- X if (nospell(spnum,mitem[x][y])) { lasthx=x; lasthy=y; return; }
- X# ifdef MSDOS
- X do {
- X m = rnd(MAXMONST+7);
- X mitem[x][y] = m;
- X } while ( monster[m].genocided );
- X# else
- X while ( monster[m = mitem[x][y] = rnd(MAXMONST+7)].genocided );
- X# endif
- X hitp[x][y] = monster[m].hitpoints;
- X show1cell(x,y); /* show the new monster */
- X }
- X
- X/*
- X * annihilate() Routine to annihilate all monsters around player (playerx,playery)
- X *
- X * Gives player experience, but no dropped objects
- X * Returns the experience gained from all monsters killed
- X */
- Xannihilate()
- X {
- X int i,j;
- X register long k;
- X register char *p;
- X for (k=0, i=playerx-1; i<=playerx+1; i++)
- X for (j=playery-1; j<=playery+1; j++)
- X if (!vxy(&i,&j)) /* if not out of bounds */
- X if (*(p= &mitem[i][j])) /* if a monster there */
- X if (*p<DEMONLORD+2)
- X {
- X# ifdef DGK
- X k += monster[*p].experience; *p=know[i][j] &= ~KNOWHERE;
- X# else
- X k += monster[*p].experience; *p=know[i][j]=0;
- X# endif
- X }
- X else
- X {
- X lprintf("\nThe %s barely escapes being annihilated!",monster[*p].name);
- X hitp[i][j] = (hitp[i][j]>>1) + 1; /* lose half hit points*/
- X }
- X if (k>0)
- X {
- X lprcat("\nYou hear loud screams of agony!"); raiseexperience((long)k);
- X }
- X return(k);
- X }
- X
- X/*
- X * genmonst() Function to ask for monster and genocide from game
- X *
- X * This is done by setting a flag in the monster[] structure
- X */
- Xstatic genmonst()
- X {
- X register int i,j;
- X cursors(); lprcat("\nGenocide what monster? ");
- X for (i=0; (!isalpha(i)) && (i!=' '); i=ttgetch());
- X lprc(i);
- X for (j=0; j<MAXMONST; j++) /* search for the monster type */
- X if (monstnamelist[j]==i) /* have we found it? */
- X {
- X monster[j].genocided=1; /* genocided from game */
- X lprintf(" There will be no more %s's",monster[j].name);
- X /* now wipe out monsters on this level */
- X newcavelevel(level); draws(0,MAXX,0,MAXY); bot_linex();
- X return;
- X }
- X lprcat(" You sense failure!");
- X }
- END_OF_FILE
- if test 27476 -ne `wc -c <'spells.c'`; then
- echo shar: \"'spells.c'\" unpacked with wrong size!
- fi
- # end of 'spells.c'
- fi
- echo shar: End of archive 5 \(of 11\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-